package autokeyboard.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

import autokeyboard.data.KeyCharMask;
import autokeyboard.data.KeyCharName;
import autokeyboard.data.TableModel;
import autokeyboard.handler.TablePanelEvent;

@SuppressWarnings({ "serial" })
public class TablePanel extends JPanel
{
	private JPanel				panel			= new JPanel(new BorderLayout());
	private JTable		table;
	private JScrollPane			scroll			= new JScrollPane();

	private KeyCharMask			keyMask			= new KeyCharMask();
	private KeyCharName			keyName			= new KeyCharName();
	private TableModel			tableModel		= new TableModel();

	private ArrayList<Object[]>	listObject		= new ArrayList<Object[]>();
	private final Object[]		listTitle		= { "Id#", "Key Stroke Info", "Key Name", "Stroke Delay" };

	public static int			rowCount		= 0;
	public static int			keyStrokeDelay	= 50;

	private TablePanelEvent		event			= new TablePanelEvent();
	private ListSelectionModel	listSelectionModel;
	private JFrame				frame;

	private JButton				btUp;
	private JButton				btDown;
	private JButton				btDelete;

	public static boolean		isChanged		= false;

	private boolean				isShift			= false;
	// private boolean isAlt = false;
	// private boolean isCtrl = false;
	private boolean				isOtherKey		= false;

	public TablePanel(JFrame frame)
	{
		this.frame = frame;
		initComponent();
		listSelectionModel = table.getSelectionModel();
		rowCount = 0;
	}

	private void initComponent()
	{
		setMainLayout();
		keyEvent();
		mouseEvent();
	}

	// =====================Setter and getter=======================//

	public JTable getTable()
	{
		return this.table;
	}

	public ArrayList<Object[]> getListObject()
	{
		return this.listObject;
	}

	public ListSelectionModel getListSelectionModel()
	{
		return this.listSelectionModel;
	}

	public void setBtUp(JButton btUp)
	{
		this.btUp = btUp;
		this.btUp.setEnabled(false);
	}

	public void setBtDown(JButton btDown)
	{
		this.btDown = btDown;
		this.btDown.setEnabled(false);
	}

	public void setBtDelete(JButton btDelete)
	{
		this.btDelete = btDelete;
		this.btDelete.setEnabled(false);
	}

	// =====================End setter and getter====================//

	private void setMainLayout()
	{
		createDefaultValueTable();
		Dimension d = this.getSize();

		this.setLayout(new BorderLayout());
		this.add(panel, BorderLayout.CENTER);

		panel.setPreferredSize(new Dimension(d.width, d.height));
		table.setFillsViewportHeight(true);
		table.setFont(new Font("Calibri", 0, 18));
	}

	/**
	 * This method will create default value to your table.
	 * <p>
	 * The default value is header name, number of column
	 */
	private void createDefaultValueTable()
	{

		final Object[][] list = new Object[0][0];
		table = new JTable(list, listTitle);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		scroll = new JScrollPane(table);
		table.setModel(tableModel.setNewModel(list));
		panel.add(scroll);

		TableCellRenderer myRenderer = table.getTableHeader().getDefaultRenderer();
		JLabel label = (JLabel) myRenderer;
		label.setHorizontalAlignment(JLabel.CENTER);

		columnAlignment(JLabel.LEFT);
	}

	/**
	 * This method will align your column in your table with your input
	 * alignment
	 * 
	 * @param alignment
	 */
	private void columnAlignment(int alignment)
	{
		DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer();
		cellRenderer.setHorizontalAlignment(alignment);
		table.getColumnModel().getColumn(0).setCellRenderer(cellRenderer);
		table.getColumnModel().getColumn(1).setCellRenderer(cellRenderer);
		table.getColumnModel().getColumn(2).setCellRenderer(cellRenderer);
		table.getColumnModel().getColumn(3).setCellRenderer(cellRenderer);
	}

	/**
	 * This method will add one more row into your table when you press any key.
	 * 
	 * @param evt
	 * @return
	 */
	private Object[][] oneMoreRow(KeyEvent evt)
	{
		final Object[][] list;

		String keyPress = "";
		if (!isShift)
			keyPress = "Key Press ";
		else if (isShift) keyPress = "Key Press SHIFT + ";

		// if(!isCtrl)
		// keyPress = "Key Press ";
		// else if(isCtrl)
		// keyPress = "Key Press CONTROL + ";
		//
		// if(!isShift)
		// keyPress = "Key Press ";
		// else if(isShift)
		// keyPress = "Key Press SHIFT + ";

		Object[] item = { ++rowCount, keyPress + keyCharShow(evt), keyChar(evt), keyStrokeDelay };
		listObject.add(rowCount - 1, item);

		list = new Object[listObject.size()][];

		for (int i = 0; i < listObject.size(); i++)
		{
			list[i] = listObject.get(i);
		}
		updateTable();
		return list;
	}

	/**
	 * This method will return a key mask with your input key
	 * <p>
	 * It use KeyEvent to get your input key
	 * 
	 * @param evt
	 * @return
	 */
	private String keyChar(KeyEvent evt)
	{
		return keyMask.keyCharMarsk(evt);
	}

	/**
	 * This method will return your key name with your input key
	 * <p>
	 * It use KeyEvent to get your input key
	 * 
	 * @param evt
	 * @return
	 */
	private String keyCharShow(KeyEvent evt)
	{
		return keyName.keyFullName(evt);
	}

	/**
	 * This method will be set key event for table when you press one key.
	 */
	private void keyEvent()
	{
		table.addKeyListener(new KeyAdapter()
		{
			@Override
			public void keyPressed(KeyEvent evt)
			{
				if (listObject.size() == 0)
					isChanged = false;
				else isChanged = true;

				if (evt.getKeyCode() == KeyEvent.VK_SHIFT) isShift = true;
				// if(evt.getKeyCode() == KeyEvent.VK_CONTROL)
				// isCtrl = true;
				// if(evt.getKeyCode() == KeyEvent.VK_ALT)
				// isAlt = true;
				// if (evt.getKeyCode() != KeyEvent.VK_SHIFT && evt.getKeyCode()
				// != KeyEvent.VK_CONTROL && evt.getKeyCode() !=
				// KeyEvent.VK_ALT)
				if (evt.getKeyCode() != KeyEvent.VK_SHIFT)
				{
					isOtherKey = true;
					setEnabledButton(true);
					/**
					 * This method will add new row into table
					 */
					table.setModel(tableModel.setNewModel(oneMoreRow(evt)));
					columnAlignment(JLabel.LEFT);

					/**
					 * If the rows in table is larger than 2 it will be
					 * automatic selected the last row
					 */
					if (table.getRowCount() >= 2)
					{
						if (rowCount == listObject.size())
							table.setRowSelectionInterval(table.getRowCount() - 2, table.getRowCount() - 1);
						else
						{
							if (rowCount >= 2)
								table.setRowSelectionInterval(rowCount - 2, rowCount - 1);
							else if (rowCount == 1) table.setRowSelectionInterval(1, 0);
						}
					}
				}

				/**
				 * If scroll is showing it will be set scroll to end of the
				 * panel
				 */
				if (scroll.isShowing())
				{
					scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getValue() + 16);
				}
			}

			@Override
			public void keyReleased(KeyEvent evt)
			{
				checkShift(evt);
				// checkCtrl(evt);
				// checkAlt(evt);
				/**
				 * If scroll is showing it will be set scroll to end of the
				 * panel
				 */

				if (scroll.isShowing() && rowCount >= listObject.size() - 1)
				{
					scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getValue() + 16);
				}
				if (evt.getKeyCode() == KeyEvent.VK_ENTER)
				{
					table.setRowSelectionInterval(rowCount - 2, rowCount - 1);
					scroll.getVerticalScrollBar().setValue(rowCount * 16);
				}
			}
		});
	}

	/**
	 * This method will check whether the shift key is press only or press with
	 * an other key
	 * 
	 * @param evt
	 */
	private void checkShift(KeyEvent evt)
	{
		if (evt.getKeyCode() == KeyEvent.VK_SHIFT)
		{
			if (isShift && isOtherKey)
			{
				isOtherKey = false;
				isShift = false;
			}
			else if (isShift && !isOtherKey)
			{
				isOtherKey = false;
				isShift = false;
				setEnabledButton(true);
				/**
				 * This method will add new row into table
				 */
				table.setModel(tableModel.setNewModel(oneMoreRow(evt)));
				columnAlignment(JLabel.LEFT);

				/**
				 * If the rows in table is larger than 2 it will be automatic
				 * selected the last row
				 */
				if (table.getRowCount() >= 2)
				{
					if (rowCount == listObject.size())
						table.setRowSelectionInterval(table.getRowCount() - 2, table.getRowCount() - 1);
					else
					{
						if (rowCount >= 2)
							table.setRowSelectionInterval(rowCount - 2, rowCount - 1);
						else if (rowCount == 1) table.setRowSelectionInterval(1, 0);
					}
				}
			}
		}
	}

	// /**
	// * This method will check whether the ctrlKey is press only or press with
	// an other key
	// * @param evt
	// */
	// private void checkCtrl(KeyEvent evt)
	// {
	// if(evt.getKeyCode() == KeyEvent.VK_SHIFT)
	// {
	// if(isCtrl && isOtherKey)
	// {
	// isOtherKey = false;
	// isCtrl = false;
	// }
	// else if(isShift && !isOtherKey)
	// {
	// isOtherKey = false;
	// isCtrl = false;
	// setEnabledButton(true);
	// /**
	// * This method will add new row into table
	// */
	// table.setModel(tableModel.setNewModel(oneMoreRow(evt)));
	// columnAlignment(JLabel.LEFT);
	//
	// /**
	// * If the rows in table is larger than 2 it will be automatic
	// * selected the last row
	// */
	// if (table.getRowCount() >= 2)
	// {
	// if (rowCount == listObject.size())
	// table.setRowSelectionInterval(table.getRowCount() - 2,
	// table.getRowCount() - 1);
	// else
	// {
	// if (rowCount >= 2)
	// table.setRowSelectionInterval(rowCount - 2, rowCount - 1);
	// else if (rowCount == 1) table.setRowSelectionInterval(1, 0);
	// }
	// }
	// }
	// }
	// }
	//
	// /**
	// * This method will check whether the altKey is press only or press with
	// an other key
	// * @param evt
	// */
	// private void checkAlt(KeyEvent evt)
	// {
	// if(evt.getKeyCode() == KeyEvent.VK_SHIFT)
	// {
	// if(isAlt && isOtherKey)
	// {
	// isOtherKey = false;
	// isAlt = false;
	// }
	// else if(isShift && !isOtherKey)
	// {
	// isOtherKey = false;
	// isAlt = false;
	// setEnabledButton(true);
	// /**
	// * This method will add new row into table
	// */
	// table.setModel(tableModel.setNewModel(oneMoreRow(evt)));
	// columnAlignment(JLabel.LEFT);
	//
	// /**
	// * If the rows in table is larger than 2 it will be automatic
	// * selected the last row
	// */
	// if (table.getRowCount() >= 2)
	// {
	// if (rowCount == listObject.size())
	// table.setRowSelectionInterval(table.getRowCount() - 2,
	// table.getRowCount() - 1);
	// else
	// {
	// if (rowCount >= 2)
	// table.setRowSelectionInterval(rowCount - 2, rowCount - 1);
	// else if (rowCount == 1) table.setRowSelectionInterval(1, 0);
	// }
	// }
	// }
	// }
	// }

	/**
	 * This method will add call event when you double click in any line on the
	 * table
	 * <p>
	 * This will get your row
	 */
	private void mouseEvent()
	{
		table.addMouseListener(new MouseAdapter()
		{
			@Override
			public void mouseClicked(MouseEvent evt)
			{
				if (evt.getClickCount() == 2)
				{
					if (!listSelectionModel.isSelectionEmpty())
					{
						int index = listSelectionModel.getMinSelectionIndex();
						Object[] list = listObject.get(index);
						event.showKeyStrokeDialog(frame, table, list, index, listObject);
					}
				}
				if (evt.getClickCount() == 1)
				{
					if (!listSelectionModel.isSelectionEmpty())
					{
						int index = listSelectionModel.getMinSelectionIndex();
						rowCount = index;
						if (index != 0) rowCount++;
						if (index == 0)
						{
							btUp.setEnabled(false);
							btDown.setEnabled(true);
						}
						else if (index == listObject.size() - 1)
						{
							btUp.setEnabled(true);
							btDown.setEnabled(false);
						}
						else
						{
							btUp.setEnabled(true);
							btDown.setEnabled(true);
						}
					}
				}
			}
		});
	}

	/**
	 * This method will set your button is enabled or disabled
	 * 
	 * @param value
	 */
	private void setEnabledButton(boolean value)
	{
		btDelete.setEnabled(value);
		if (listObject.size() == 1)
		{
			btDown.setEnabled(value);
			btUp.setEnabled(value);
		}
		else if (listObject.size() != 1)
		{
			btUp.setEnabled(value);
			btDown.setEnabled(!value);
			if (rowCount != listObject.size()) btDown.setEnabled(value);

		}
	}

	/**
	 * This method will update current index in the table
	 */
	public void updateTable()
	{
		for (int i = 0; i < listObject.size(); i++)
		{
			listObject.get(i)[0] = i + 1 + "";
		}
	}
}
